package com.bohan.simpage;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.json.JSONArray;
import org.json.JSONException;

import com.bohan.main.Main;
import com.bohan.main.WriterJason;



public class SimPage {

	HashMap <String, Integer> linkMat;
	HashMap <String, Double> simMatOut;
	HashMap <String, Double> simMatIn;
	ArrayList<Integer>[] matrixNeighOut;
	ArrayList<Integer>[] matrixNeighIn;
	public SimPage(int size)
	{
		linkMat = new HashMap<String, Integer>();
		simMatOut = new HashMap<String, Double>();
		simMatIn = new HashMap<String, Double>();
	}
	public ArrayList <Integer>[] getNeighOut()
	{
		return matrixNeighOut;
	}
	public ArrayList <Integer>[] getNeighIn()
	{
		return matrixNeighIn;
	}
	public void setNeigh(int size)
	{
		matrixNeighOut = new ArrayList[size];
		for(int i = 0; i < size; i ++)
			matrixNeighOut[i] = new ArrayList<Integer>();
		matrixNeighIn = new ArrayList[size];
		for(int i = 0; i < size; i ++)
			matrixNeighIn[i] = new ArrayList<Integer>();
	}
	public String showIn(int result, String fileIn, String fileSim) throws IOException, NumberFormatException, JSONException
	{
		List< Map.Entry<String, Double> > list = new ArrayList< Map.Entry<String, Double> >(simMatIn.entrySet());
        Collections.sort(list,new Comparator< Map.Entry<String ,Double> >() {
			public int compare(Entry<String, Double> o1,
					Entry<String, Double> o2) {
				if(o2.getValue().compareTo(o1.getValue()) == 0)
					return -o2.getKey().compareTo(o1.getKey());
				return o2.getValue().compareTo(o1.getValue());
			}

        });

        WriterJason wj = new WriterJason();
        return wj.write2Jason(fileIn, fileSim, list, linkMat , result);
        /*
        for(Map.Entry<String, Double> mapping : list){
        	String []s = mapping.getKey().split(",");
    		if(s[0].compareTo(s[1]) == 0)
    				continue;
    		//System.out.println(mapping.getKey());
    		if(linkMat.get(mapping.getKey()) != null)
    		{		
    			continue;
    		}
        	if(result -- > 0)
        		//System.out.println(mapping.getKey() + " " + mapping.getValue());
        		System.out.println(mapping.getKey());
    		else
    			break;
        }
		*/
	}
	public void showOut(int result)
	{
		List< Map.Entry<String, Double> > list = new ArrayList< Map.Entry<String, Double> >(simMatOut.entrySet());
        Collections.sort(list,new Comparator< Map.Entry<String ,Double> >() {
			public int compare(Entry<String, Double> o1,
					Entry<String, Double> o2) {
				if(o2.getValue().compareTo(o1.getValue()) == 0)
					return -o2.getKey().compareTo(o1.getKey());
				return o2.getValue().compareTo(o1.getValue());
			}

        });
        for(Map.Entry<String, Double> mapping : list){
        		String []key = mapping.getKey().split(",");
        		if(key[0].compareTo(key[1]) == 0)
        				continue;
        		if(linkMat.get(mapping.getKey()) != null)
        		{
        			continue;
        		}
        		if(result -- > 0)
        	//		System.out.println(mapping.getKey() + " " + mapping.getValue());
        			System.out.println(mapping.getKey());
    			else
    				break;
        }
		
	}
	public void clear(ArrayList <Integer> [] neighOut, ArrayList <Integer> [] neighIn)
	{
		linkMat = null;
		simMatOut = null;
		simMatIn = null;
		neighOut = null;
		neighIn = null;
	}
	public void readFile(String filename) throws NumberFormatException, IOException
	{
		File f = new File(filename);
		InputStream in = new FileInputStream(f);
		InputStreamReader ir = new InputStreamReader(in);
		BufferedReader br = new BufferedReader(ir);
		int ch = -1, first2Count = 0, firstNum = 0, secondNum = 0;
		String firstStr = "", secondStr = "";
		String num = "";
		
		while( (ch = br.read()) != -1 )
		{
			num += (char)ch;
			if(ch == '\t')
			{
				first2Count ++;
				if(first2Count == 1)
				{
					firstStr = num.trim();
					firstNum = Integer.parseInt(firstStr);
				}
				if(first2Count == 2)
				{
					secondStr = num.trim();
					secondNum = Integer.parseInt(secondStr);
					if(firstNum < Main.datarange && secondNum < Main.datarange){
						if(linkMat.get(firstStr + "," + secondStr) == null )
						{
							linkMat.put(firstStr + "," + secondStr, 1);
						
							matrixNeighOut[firstNum].add(secondNum);
							if(simMatOut.get(firstNum + "," + firstNum) == null)
								simMatOut.put(firstNum + "," + firstNum, 1.0);
		
							matrixNeighIn[secondNum].add(firstNum);
							if(simMatIn.get(secondNum + "," + secondNum)== null)
								simMatIn.put(secondNum + "," + secondNum, 1.0);
						}
					}
				}
				num = "";
			}
			if(ch == '\n'){
				first2Count = 0;
				num = "";
			}
		}
		br.close();
		ir.close();
		in.close();
	}
	public double computeOut(ArrayList <Integer> []matrixNeighOut, int size)
	{
		double sum = 0.0;
		double put;
		for(int i = 0; i < size ; i ++){
			for(int j = 0; j < size ; j ++)
			{
				if(simMatOut.get(i + "," + j) == null){
					put = Theata(i, j, matrixNeighOut, simMatOut);	
					if(put != 0.0 && i != j ){
							simMatOut.put(i + "," + j, put);
				
					}
				}
			}
		}
		return sum;
	}
	
	public double computeIn(ArrayList <Integer> []matrixNeighIn, int size)
	{
		double sum = 0.0;
		double put;
		int k = Main.iter;
		while(k -- > 0){
			for(int i = 0; i < size ; i ++)
				for(int j = 0; j < size ; j ++)
				{
						put = Theata(i, j, matrixNeighIn, simMatIn);
						if(put != 0.0 ){//&& i != j ){
							
							simMatIn.put(i + "," + j, put);
					}
				}
		}
		return sum;
	}
	
	double Theata(int x, int y, ArrayList <Integer> []matrixNeigh ,HashMap <String, Double> simMatrix)
	{
		int xSize, ySize;
		Iterator <Integer> itX, itY;

		double sumTemp = 0.0;

		int  ix, iy;

		xSize = matrixNeigh[x].size();
		ySize = matrixNeigh[y].size();
		if(xSize == 0 || ySize == 0){
			return 0.0;
		}
		itX = matrixNeigh[x].iterator();
		
		for(; itX.hasNext();){
			ix = itX.next();
			for(itY = matrixNeigh[y].iterator(); itY.hasNext();)
			{
				iy = itY.next();
				if(simMatrix.get(ix + "," + iy) != null){
					sumTemp += simMatrix.get(ix + "," + iy);
				}
			}
		}
		return (Main.gamma *sumTemp / (xSize * ySize));
		//return sumTemp;
	}
}
